feat(plugin): add API-key Kiro provider - #4816
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cbaa322af2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8a7f826df5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if len(payload.ConversationState.History) >= 2 && payload.ConversationState.History[0].UserInputMessage != nil && payload.ConversationState.History[1].AssistantResponseMessage != nil { | ||
| removeAt = 2 |
There was a problem hiding this comment.
Evict the oldest conversation turns when truncating
For an oversized conversation without a system prompt, the normal first user/assistant pair satisfies this condition, so truncation preserves that pair and starts deleting newer entries at index 2. If the first turn contains most of the data, the payload can remain above maxKiroPayloadBytes and the function still exits once four history entries remain; even when it becomes small enough, it has discarded newer context instead of the oldest turn. Distinguish the synthetic system pair from an ordinary first turn and evict complete oldest turns accordingly.
Useful? React with 👍 / 👎.
| @@ -1,4 +1,5 @@ | |||
| EXAMPLES := simple model auth frontend-auth executor protocol-format request-translator request-normalizer response-translator response-normalizer thinking usage cli management-api host-callback host-callback-auth-files host-model-callback claude-web-search-router | |||
| GO_ONLY_EXAMPLES := kiro | |||
There was a problem hiding this comment.
Rebuild Kiro when any Go source changes
Adding Kiro to this Makefile target exposes it to the existing Go pattern rule, whose prerequisites include only kiro/go/main.go and kiro/go/go.mod. Because this plugin's implementation is split across many additional .go files, editing files such as translate.go, auth.go, or executor.go after the first build leaves bin/kiro-go.so considered up to date, so make build-kiro silently serves a stale plugin. Include all package Go sources in the target dependencies.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3390aa71a7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for _, line := range bytes.Split(payload, []byte("\n")) { | ||
| trimmed := bytes.TrimSpace(line) | ||
| if bytes.HasPrefix(trimmed, []byte("data:")) { | ||
| dataLines = append(dataLines, bytes.Clone(trimmed)) |
There was a problem hiding this comment.
Buffer partial SSE records before translating chunks
Executor payloads are arbitrary raw chunks rather than complete SSE records (sdk/pluginapi/types.go:900-903), but this loop treats every data: fragment in the current chunk as a complete translation unit. When a chunk ends partway through a data line after an earlier newline—for example, event: ...\ndata: {"type":—the malformed fragment is discarded by the fallback check, and the continuation in the next chunk has no data: prefix, so response content is lost whenever host-side format translation is active. Retain incomplete SSE data across chunks and translate only complete records.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a779ef54ce
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Temperature float64 `json:"temperature,omitempty"` | ||
| TopP float64 `json:"topP,omitempty"` |
There was a problem hiding this comment.
Preserve explicit zero sampling values
When a valid Claude request specifies temperature: 0 or top_p: 0, these omitempty fields are removed while marshaling the Kiro payload, so the upstream service receives neither setting and applies its default instead of the caller's requested sampling behavior. Track field presence or use pointers so explicit zero values remain distinguishable from omitted parameters.
Useful? React with 👍 / 👎.
| default: | ||
| return coreusage.Detail{}, false |
There was a problem hiding this comment.
Parse usage for Gemini plugin outputs
For a plugin executor whose native output format is gemini, this default branch causes every non-streaming response to publish a zero-token record even when it contains usageMetadata; the streaming switch below omits Gemini in the same way. This undercounts usage and billing for Gemini-native plugins despite the existing helps.ParseGeminiUsage and helps.ParseGeminiStreamUsage parsers.
Useful? React with 👍 / 👎.
| func observePluginExecutorStreamChunk(buffer *helps.StreamUsageBuffer, format sdktranslator.Format, pending, payload []byte) []byte { | ||
| pending = append(pending, payload...) | ||
| lastNewline := bytes.LastIndexByte(pending, '\n') |
There was a problem hiding this comment.
Avoid buffering unsupported stream formats
When a plugin uses a custom or otherwise unsupported output format and emits chunks without newline bytes, this append retains a duplicate of the entire stream until completion even though observePluginExecutorStreamUsage has no parser for that format. Since executor chunks are arbitrary raw payloads, a long custom-format stream can therefore consume memory proportional to the complete response; bypass line buffering for formats with no usage parser.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3d78574e4d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| var dataLines [][]byte | ||
| for _, line := range bytes.Split(payload, []byte("\n")) { | ||
| trimmed := bytes.TrimSpace(line) | ||
| if bytes.HasPrefix(trimmed, []byte("data:")) { | ||
| dataLines = append(dataLines, bytes.Clone(trimmed)) |
There was a problem hiding this comment.
Reassemble multi-line SSE data before translation
Even with the new record buffer supplying a complete SSE event, this loop sends every data: field to the protocol translator independently. SSE permits an event's data to span multiple data: lines, which must be joined with newline characters; a pretty-printed JSON event is therefore split into individually invalid fragments and discarded by the fallback check, losing response content whenever host-side format translation is active.
Useful? React with 👍 / 👎.
| } | ||
| for { | ||
| raw, errMarshal := json.Marshal(payload) | ||
| if errMarshal != nil || len(raw) <= maxKiroPayloadBytes || len(payload.ConversationState.History) <= protected { |
There was a problem hiding this comment.
Reject payloads that remain above Kiro's size cap
When the oversized content is the current user message, history is empty and this condition exits immediately while the marshaled payload still exceeds maxKiroPayloadBytes; the same happens when a protected system prompt alone exceeds the cap. Such requests are sent upstream without enforcing the plugin's declared 900 KiB limit, so they fail as opaque upstream errors rather than being reduced or rejected locally.
Useful? React with 👍 / 👎.
| if request.Thinking != nil { | ||
| kind := strings.ToLower(strings.TrimSpace(request.Thinking.Type)) | ||
| if kind == "enabled" || kind == "adaptive" { | ||
| systemPrompt = strings.TrimSpace("<thinking_mode>enabled</thinking_mode>\n<max_thinking_length>200000</max_thinking_length>\n\n" + systemPrompt) |
There was a problem hiding this comment.
Honor the requested thinking budget
For a Claude request such as thinking: {"type":"enabled","budget_tokens":1024}, the request struct discards budget_tokens and this translation always tells Kiro to allow 200,000. The provider can consequently spend far more of the response budget on reasoning than the caller requested; carry the canonical budget through the provider translation instead of replacing it with a constant.
AGENTS.md reference: AGENTS.md:L29-L29
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0521c4cf75
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| switch format { | ||
| case sdktranslator.FormatClaude: | ||
| detail, ok := helps.ParseClaudeStreamUsage(line) | ||
| buffer.Observe(detail, ok) |
There was a problem hiding this comment.
Preserve earlier Claude usage fields across SSE events
When a Claude-native plugin emits input and cache counts in message_start but only output_tokens in the final message_delta, this Observe call replaces the earlier detail with the output-only detail because StreamUsageBuffer keeps the latest observation. The resulting billing record loses all input and cache tokens; merge fields from successive Claude usage events instead of treating each partial usage object as a complete replacement.
Useful? React with 👍 / 👎.
| } | ||
|
|
||
| func observePluginExecutorStreamUsage(buffer *helps.StreamUsageBuffer, format sdktranslator.Format, payload []byte) { | ||
| for _, line := range bytes.Split(payload, []byte("\n")) { |
There was a problem hiding this comment.
Reassemble multi-line SSE data before parsing usage
When a plugin encodes a usage JSON object across multiple legal SSE data: fields, this loop sends each physical line independently to the JSON usage parser, so every fragment is invalid and the request is recorded with zero tokens. Reassemble all data: fields in each complete SSE event, as the response-translation path now does, before parsing its usage payload.
Useful? React with 👍 / 👎.
| if input == nil { | ||
| input = map[string]any{} | ||
| } | ||
| tools = append(tools, kiroToolUse{ToolUseID: id, Name: sanitizeToolName(name), Input: input}) |
There was a problem hiding this comment.
Apply tool-name disambiguation to assistant history
When two valid tool names sanitize to the same value—for example foo and foo_—convertTools exposes them as foo and foo_2, but historical assistant calls of foo_ are converted here to plain foo. Kiro therefore receives history claiming that the first tool produced the second tool's call/result, which can corrupt subsequent tool selection; translate historical names through the same original-to-disambiguated mapping used for the declarations.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 893017d920
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if strings.HasPrefix(strings.ToLower(tool.Type), "web_search") { | ||
| continue | ||
| } | ||
| name := uniqueToolName(sanitizeToolName(tool.Name), used) |
There was a problem hiding this comment.
Reserve every emitted tool name globally
When distinct valid tool names sanitize into a generated suffix that is itself another tool's base name—for example foo, foo_, and foo_2—this produces foo, foo_2, and foo_2. Kiro then receives duplicate tool declarations, while nameMap["foo_2"] is overwritten, so calls may be rejected or mapped back to the wrong Claude tool; uniqueness must be checked against all emitted names, not only the counter for each sanitized base.
Useful? React with 👍 / 👎.
| } | ||
| payload.ConversationState.CurrentMessage.UserInputMessage = current | ||
| payload.ConversationState.History = trimLeadingAssistant(history) | ||
| payload.EstimatedInputTokens = estimateClaudeRequestInputTokens(&request) |
There was a problem hiding this comment.
Recalculate usage after truncating history
For requests whose old history is removed to satisfy the 900 KiB payload cap, this estimate is calculated from the original Claude request before truncatePayload mutates the outgoing history. If Kiro omits explicit token counts and a context-usage event, responseAccumulator.finish publishes this stale value in the Claude response and the host billing record, potentially charging for hundreds of thousands of tokens that were never sent upstream; derive the fallback estimate from the retained payload after truncation.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7bb800a840
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| case "reasoningContentEvent": | ||
| if text := firstStringField(event.Payload, "text", "content"); text != "" { | ||
| block := claudeContentBlock{Type: "thinking", Thinking: text} | ||
| a.appendFragment(block) | ||
| return []claudeContentBlock{block}, nil |
There was a problem hiding this comment.
Emit protocol-valid signatures for thinking blocks
When Kiro returns a reasoningContentEvent, this creates an Anthropic thinking block without the required signature; the streaming writer likewise emits thinking_delta events but never a signature_delta. Clients that validate Claude responses or replay thinking blocks during a subsequent tool/user turn therefore receive unusable reasoning state. Supply a protocol-compatible signature or avoid exposing unsigned reasoning as a Claude thinking block.
Useful? React with 👍 / 👎.
| if index := bytes.Index(payload, []byte("\n\n")); index >= 0 { | ||
| end = index + 2 | ||
| } | ||
| if index := bytes.Index(payload, []byte("\r\n\r\n")); index >= 0 && (end < 0 || index+4 < end) { | ||
| end = index + 4 |
There was a problem hiding this comment.
Recognize CR-only SSE record delimiters
For a plugin that emits valid SSE using carriage-return line endings, this record scanner never finds the \r\r blank-line delimiter and buffers the entire stream until close. The translation path then receives all CR-delimited events as one payload and typically drops them as an untranslated fallback, while usage parsing also misses the records. Recognize CR-only separators in addition to LF and CRLF.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b9e9dd1165
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| *candidates = append(*candidates, nested) | ||
| } | ||
| } | ||
| collectUsageMaps(child, candidates) |
There was a problem hiding this comment.
Limit usage scanning to provider metadata
When a Kiro tool-use event supplies input as an object containing a user-controlled nested usage map, this unrestricted recursion adds that map as a token-usage candidate. Because responseAccumulator.accept runs updateUsage for every event, tool arguments such as {"usage":{"inputTokens":100000}} can overwrite the real counts returned in the Claude response and billing record; only known provider usage locations should be inspected.
Useful? React with 👍 / 👎.
| Type string `json:"type,omitempty"` | ||
| BudgetTokens int `json:"budget_tokens,omitempty"` | ||
| } `json:"thinking,omitempty"` | ||
| Tools []claudeTool `json:"tools,omitempty"` |
There was a problem hiding this comment.
Preserve Claude tool_choice constraints
For a valid Claude request with tool_choice set to any, none, or a specific tool, unmarshalling into this struct silently discards the field, while all declared tools are still sent to Kiro with its default selection behavior. A caller forcing one tool can therefore receive text or a call to another tool, and a caller disabling tools can still get a tool call; translate this constraint or reject unsupported choices rather than ignoring it.
Useful? React with 👍 / 👎.
| if errPrepare != nil { | ||
| return errorEnvelope("invalid_request", errPrepare.Error(), http.StatusBadRequest, false), nil |
There was a problem hiding this comment.
Classify missing API keys as authentication failures
When an api_key_env variable is unset or empty, prepareUpstreamRequest fails in resolveAPIKey, but this branch—and the equivalent streaming branch—returns invalid_request with HTTP 400. This misclassifies a broken credential as a caller payload error, so clients and host auth handling cannot treat it like the 401 invalid_auth failures used elsewhere; distinguish credential-resolution errors from Claude request-validation errors.
Useful? React with 👍 / 👎.
b9e9dd1 to
0f4621e
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0f4621e686
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| MaxTokens int `json:"max_tokens"` | ||
| Temperature *float64 `json:"temperature,omitempty"` | ||
| TopP *float64 `json:"top_p,omitempty"` | ||
| Stream bool `json:"stream,omitempty"` | ||
| System any `json:"system,omitempty"` |
There was a problem hiding this comment.
For a valid Claude request containing stop_sequences, unmarshalling into this struct silently drops the field, so Kiro can continue generating past the caller's requested delimiter and report a different stop reason. Translate the sequences into the upstream inference configuration, or reject them explicitly if Kiro cannot support them.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 020f69db01
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| rawResponse, errCall := invokeHost(pluginabi.MethodHostHTTPDoStream, rpcHostHTTPRequest{ | ||
| HostCallbackID: hostCallbackID, | ||
| Method: http.MethodPost, | ||
| URL: request.URL, | ||
| Headers: headers, |
There was a problem hiding this comment.
Route callbacks through the selected auth's HTTP client
When a Kiro credential specifies proxy_url—especially direct/none to bypass a global proxy—this callback carries only the generic host callback ID, and internal/pluginhost/host_callbacks.go handles it with h.newHTTPClient(nil). Consequently both runtime requests here and model-discovery requests ignore the selected auth's proxy policy, potentially failing where Kiro is reachable only through that proxy or sending the API key through a global proxy the credential explicitly bypasses; associate these callbacks with the auth-aware HTTP client created in buildExecutorRequest.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: af3d873212
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| data, _ := source["data"].(string) | ||
| mediaType, _ := source["media_type"].(string) | ||
| if data == "" { | ||
| return nil |
There was a problem hiding this comment.
Preserve URL-backed image inputs
When a valid Claude image block uses source: {"type":"url","url":"..."}, this reads only source.data, returns nil, and silently removes the image; an image-only prompt is consequently replaced with the "." fallback and Kiro answers without seeing the attachment. This also affects OpenAI-compatible requests because the repository's OpenAI-to-Claude translators emit URL-backed image blocks, so either fetch/forward these images or reject the unsupported source type instead of dropping it.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f11a111bc3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if errMajor == nil && (major > 4 || major == 4 && minor >= 6) { | ||
| return 1_000_000 |
There was a problem hiding this comment.
Distinguish dated snapshots from minor versions
When Kiro reports only contextUsagePercentage for a dated model such as claude-opus-4-20250514, claudeVersionPattern parses 20250514 as the minor version, so this branch assumes a 1,000,000-token context instead of the model's 200,000-token context. currentInputTokens then overstates fallback input usage by 5× in both the Claude response and the host billing record; recognize date suffixes separately or derive the context limit from discovered model metadata.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ba9e808625
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| func mergeClaudePluginStreamUsage(previous, current coreusage.Detail) coreusage.Detail { | ||
| current.InputTokens = max(previous.InputTokens, current.InputTokens) |
There was a problem hiding this comment.
Let final Claude usage replace provisional estimates
When a Kiro stream emits answer content before its later context/token-usage event, message_start contains EstimatedInputTokens while the final message_delta contains the authoritative count. Taking the maximum prevents that final event from correcting an overestimate, so the plugin usage reporter can overcount billing; preserve an earlier field only when the later usage object omits it rather than whenever it is smaller.
Useful? React with 👍 / 👎.
| case "reasoningContentEvent": | ||
| // Kiro does not return an Anthropic-verifiable signature. Omit its | ||
| // reasoning instead of emitting a Claude thinking block that clients | ||
| // cannot safely replay. | ||
| return nil, nil |
There was a problem hiding this comment.
Count hidden reasoning in fallback usage
When Kiro emits reasoningContentEvent frames but omits explicit output-token metrics, this return discards the only representation of those generated tokens. finish() subsequently estimates output solely from the visible blocks in a.Blocks, so a request using a large thinking budget can report and bill only the short visible answer; retain enough reasoning information to include it in fallback token accounting even if unsigned reasoning cannot be exposed to the client.
Useful? React with 👍 / 👎.
| resultRaw, errCall := invokeHost(pluginabi.MethodHostHTTPDo, rpcHostHTTPRequest{ | ||
| HostCallbackID: request.HostCallbackID, |
There was a problem hiding this comment.
Pass the auth client through executor HTTP callbacks
When the host uses executorAdapter.HttpRequest for a Kiro credential with proxy_url, this callback still runs through a context opened by rpcPluginAdapter.HttpRequest without req.HTTPClient, so host.http.do falls back to the generic client and ignores the selected credential's proxy or direct policy. Fresh evidence beyond the earlier runtime/model-discovery report is that this separate newly added executorHTTPRequest path invokes the host callback while its RPC caller still omits the auth-aware client.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e99dc770a9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| volumes: | ||
| - ${CLI_PROXY_CONFIG_PATH:-./config.yaml}:/CLIProxyAPI/config.yaml | ||
| - ${CLI_PROXY_AUTH_PATH:-./auths}:/root/.cli-proxy-api | ||
| - ${CLI_PROXY_AUTH_PATH:-./auths}:/CLIProxyAPI/auths |
There was a problem hiding this comment.
Restore the Compose auth mount to the configured directory
When using the repository's default auth-dir (~/.cli-proxy-api, also shown in config.example.yaml), the process scans /root/.cli-proxy-api, but this bind mount now places the host credentials under /CLIProxyAPI/auths. Consequently a normal Compose restart makes every JSON credential in the default ./auths directory invisible and can leave the server with no available auth; either restore the /root/.cli-proxy-api destination or explicitly align auth-dir with the new mount.
Useful? React with 👍 / 👎.
Summary
Why
CLIProxyAPI's plugin architecture can support Kiro without adding a built-in provider or duplicating the host's credential selection, session affinity, cooldown, proxy, logging, and protocol-routing infrastructure. The plugin keeps the integration isolated and uses the host HTTP bridge for outbound requests.
API keys can be referenced through
api_key_env, so the resolved value does not need to be written into an auth JSON file.Request flow
kiro.Contribution-policy note
This PR targets
devand does not modifyinternal/translator/**.Complete non-streaming OpenAI Chat Completions and Responses compatibility needs a small maintainer-owned translator change. It is tracked in #4815 with an isolated reference patch, as required by the repository's translator path guard. Claude
/v1/messagesis supported directly by this PR.Validation
go test ./...go test ./...inexamples/plugin/kiro/gogo build -o /tmp/cliproxyapi-upstream-pr-build ./cmd/servergofmton all changed Go filesgit diff --check origin/dev...HEADLimitations
/v1/messages/count_tokensis a clearly marked local estimate.Provenance
The runtime protocol implementation was informed by the MIT-licensed Kiro-Go project at revision
f8f6071c9298a4266ad3e0c7e483d4a2510cbcaf. Details are included inexamples/plugin/kiro/THIRD_PARTY_NOTICES.md.